import axios from 'axios'
import { createStore, Commit } from 'vuex'

export interface ResponseType<P = {}> {
  code: number
  msg: string
  data: P
}

export interface ImageProps {
  _id?: string
  url?: string
  createdAt?: string
  fitUrl?: string
}

export interface PostProps {
  _id?: string
  title: string
  excerpt?: string
  content?: string
  image?: ImageProps
  createdAt?: string
  column: string
  author?: string | UserProps
}

export interface ColumnProps {
  _id: string
  title: string
  avatar?: ImageProps
  description: string
}

export interface UserProps {
  token: string
  isLogin: boolean
  nickName?: string
  _id?: string
  column?: string
  email?: string
  avatar?: ImageProps
  description?: string
}

export interface GlobalErrorProps {
  status: boolean
  message?: string
}

export interface GlobalDataProps {
  error: GlobalErrorProps
  loading: boolean
  columns: ColumnProps[]
  posts: PostProps[]
  user: UserProps
}

const getAndCommit = async (url: string, mutationName: string, commit: Commit) => {
  const { data } = await axios.get(url)
  commit(mutationName, data)
  return data
}

const postAndCommit = async (url: string, mutationName: string, commit: Commit, payload: any) => {
  const { data } = await axios.post(url, payload)
  commit(mutationName, data)
  return data
}

const store = createStore<GlobalDataProps>({
    state: {
      error: { status: false },
      token: localStorage.getItem('token') || '',
      loading: false,
      columns: [],
      posts: [],
      user: { isLogin: false }
    },
    mutations: {
      login (state: { user: UserProps }, rawData: any) {
        const { token } = rawData.data
        state.user.token = token
        localStorage.setItem('token', token)
        axios.defaults.headers.common.Authorization = `Bearer ${token}`
      },
      loginout (state: UserProps) {
        state.isLogin = false
        state.token = ''
        localStorage.removeItem('token')
        delete axios.defaults.headers.common.Authorization
      },
      createPost(state: { posts: PostProps[] }, newPost: PostProps) {
        state.posts.push(newPost)
      },
      fetchColumns (state: { columns: ColumnProps[] }, rawData: any) {
        state.columns = rawData.data.list
      },
      fetchColumn (state: { columns: ColumnProps[] }, rawData: any) {
        state.columns = [rawData.data]
      },
      fetchPosts (state: { posts: PostProps[] }, rawData: any) {
        state.posts = rawData.data.list
      },
      fetchPost(state: { posts: any[] }, rawData: { data: any }) {
        state.posts = [rawData.data]
      },
      fetchCurrentUser (state: { user: UserProps }, rawData: any) {
        state.user = { isLogin: true, ...rawData.data }
      },
      // 增加全局loading状态
      setLoading (state: { loading: boolean }, status: boolean) {
        state.loading = status
      },
      // 增加全局error状态
      setError (state: { error: GlobalErrorProps }, e: GlobalErrorProps) {
        state.error = e
      }
    },
    actions: {
      fetchColumns ({commit}: any) {
        return getAndCommit('/columns', 'fetchColumns', commit)
      },
      fetchColumn ({commit}: any, id: string) {
        return getAndCommit(`/columns/${id}`, 'fetchColumn', commit)
      },
      fetchPosts ({commit}: any, cid: string) {
        return getAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit)
      },
      fetchPost({ commit }: any, id: any) {
        return getAndCommit(`/posts/${id}`, 'fetchPost', commit)
      },
      fetchCurrentUser ({commit}: any) {
        return getAndCommit('/user/current', 'fetchCurrentUser', commit)
      },
      createPost ({commit}: any, payload: any) {
        return postAndCommit('/posts', 'createPost', commit, payload)
      },
      login ({commit}: any, payload: any) {
        return postAndCommit('/user/login', 'login', commit, payload)
      },
      loginAndFetch ({dispatch}: any, loginData: any) {
        return dispatch('login', loginData).then(() => {
          return dispatch('fetchCurrentUser')
        })
      },
    },
    getters: {
      getColumnById: (state: { columns: ColumnProps[] }) => (id: string) => {
        return state.columns.find(c => c._id === id)
      },
      getPostsByCid: (state: { posts: PostProps[] }) => (cid: string) => {
        return state.posts.filter(post => post.column === cid)
      },
      getCurrentPost: (state: { posts: PostProps[] }) => (id: string) => {
        return state.posts.find(post => post._id === id)
      }
    }
  })

  export default store
